/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package CastleDefense.Managers;

import CastleDefense.*;
import CastleDefense.units.PlacedUnit;
import CastleDefense.units.PlacedUnit.StateEffect;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Firedemon
 */
public class StateManager
{
    private long currentTime;

    public void updateStateEffects(Enemy target)
    {
        List<StateEffect> states = target.getStates();
        currentTime  = System.currentTimeMillis();

        if(target.isSlowed())
        {
            if(currentTime - target.getFirstSlowed() > target.getSlowDuration())
            {
                target.resetSpeed();
                target.setFirstSlowed(0);
                target.setSlowDuration(0);
                target.setSlowed(false);
            }
        }
        
        if(target.isSnared())
        {
            target.setSnareTime(target.getSnareDuration()-(currentTime - target.getFirstSnared()));
            if(currentTime - target.getFirstSnared() > target.getSnareDuration())
            {
                target.resetSpeed();
                target.setFirstSnared(0);
                target.setSnareDuration(0);
                target.setSnared(false);
            }
        }

        if(states.contains(StateEffect.NONE))
        {/*'Non' pjojectiles don't do anything*/}
        if(states.contains(StateEffect.POISON))
        {
            target.setPoisoned(true);
            target.removeState(StateEffect.POISON);
        }
        if(states.contains(StateEffect.SLOW))
        {
            if(target.isSnared())
                return;
            
            double delta = 3.5;

            target.setSpeed(delta);
            target.setFirstSlowed(System.currentTimeMillis());
            target.setSlowDuration(5000);
            target.removeState(StateEffect.SLOW);
            target.setSlowed(true);
        }
        if(states.contains(StateEffect.SNARE))
        {
            double delta = 0;

            target.setSpeed(delta);
            target.setFirstSnared(System.currentTimeMillis());
            target.setSnareDuration(10000);
            target.removeState(StateEffect.SNARE);
            target.setSnared(true);
        }
    }

    public void doPoisonTick(Enemy target, PlacedUnit p)
    {
        UpgradeManager um = new UpgradeManager();
        
        if(target.isPoisoned())
        {
            int psnDmg  = um.getCurrentPoisonDamage();
            int steps   = target.getSteps();
            if(steps>target.getStepCounter())
            {
                target.setStepCounter(steps);
                target.doDamageCalculation(psnDmg, p);
            }
        }
    }

    public void doSplashDamage(double damage, Enemy target, PlacedUnit p)
    {
        if(target.getStates().contains(StateEffect.SPLASH))
        {
            List<Enemy> enemyList = getNearbyEnemies(target, 1);

            for(Enemy effected : enemyList)
            {
                if(effected != null)
                     effected.doDamageCalculation((damage/2), p);
            }
        }
    }

    public List<Enemy> getNearbyEnemies(Enemy target, int tileDist)
    {
        
        List<Enemy> splashDmgList = new ArrayList<Enemy>();

        for(int i=1; i<=tileDist; i++)
        {
            int delta1 = (i*42);
            
            //east
            if(Game.checkForEnemy(target.getMidX()+delta1, target.getMidY()) != null)
                splashDmgList.add(Game.checkForEnemy(target.getMidX()+delta1, target.getMidY()));

            //south
            if(Game.checkForEnemy(target.getMidX(), target.getMidY()+delta1-1) != null)
                splashDmgList.add(Game.checkForEnemy(target.getMidX(), target.getMidY()+delta1-1));

            //north
            if(Game.checkForEnemy(target.getMidX(), target.getMidY()-delta1) != null)
                splashDmgList.add(Game.checkForEnemy(target.getMidX(), target.getMidY()-delta1));

            //west
            if(Game.checkForEnemy(target.getMidX()-delta1, target.getMidY()) != null)
                splashDmgList.add(Game.checkForEnemy(target.getMidX()-delta1, target.getMidY()));
            
            //north west
            if(Game.checkForEnemy(target.getMidX()-delta1, target.getMidY()-delta1) != null)
                splashDmgList.add(Game.checkForEnemy(target.getMidX()-delta1, target.getMidY()-delta1));

            //south west
            if(Game.checkForEnemy(target.getMidX()-delta1, target.getMidY()+delta1) != null)
                splashDmgList.add(Game.checkForEnemy(target.getMidX()-delta1, target.getMidY()+delta1));

            //north east
            if(Game.checkForEnemy(target.getMidX()+delta1, target.getMidY()-delta1) != null)
                splashDmgList.add(Game.checkForEnemy(target.getMidX()+delta1, target.getMidY()-delta1));

            //south east
            if(Game.checkForEnemy(target.getMidX()+delta1, target.getMidY()+delta1) != null)
               splashDmgList.add(Game.checkForEnemy(target.getMidX()+delta1, target.getMidY()+delta1));

        }
        
        return splashDmgList;
    }
    
    public List<Enemy> getNearbyEnemies(PlacedUnit target, int tileDist)
    {  
        List<Enemy> splashDmgList = new ArrayList<Enemy>();

        for(int i=1; i<=tileDist; i++)
        {
            int delta1 = (i*42);
            
            //east
            if(Game.checkForEnemy(target.getMidX()+delta1, target.getMidY()) != null)
                splashDmgList.add(Game.checkForEnemy(target.getMidX()+delta1, target.getMidY()));

            //south
            if(Game.checkForEnemy(target.getMidX(), target.getMidY()+delta1-1) != null)
                splashDmgList.add(Game.checkForEnemy(target.getMidX(), target.getMidY()+delta1-1));

            //north
            if(Game.checkForEnemy(target.getMidX(), target.getMidY()-delta1) != null)
                splashDmgList.add(Game.checkForEnemy(target.getMidX(), target.getMidY()-delta1));

            //west
            if(Game.checkForEnemy(target.getMidX()-delta1, target.getMidY()) != null)
                splashDmgList.add(Game.checkForEnemy(target.getMidX()-delta1, target.getMidY()));
            
            //north west
            if(Game.checkForEnemy(target.getMidX()-delta1, target.getMidY()-delta1) != null)
                splashDmgList.add(Game.checkForEnemy(target.getMidX()-delta1, target.getMidY()-delta1));

            //south west
            if(Game.checkForEnemy(target.getMidX()-delta1, target.getMidY()+delta1) != null)
                splashDmgList.add(Game.checkForEnemy(target.getMidX()-delta1, target.getMidY()+delta1));

            //north east
            if(Game.checkForEnemy(target.getMidX()+delta1, target.getMidY()-delta1) != null)
                splashDmgList.add(Game.checkForEnemy(target.getMidX()+delta1, target.getMidY()-delta1));

            //south east
            if(Game.checkForEnemy(target.getMidX()+delta1, target.getMidY()+delta1) != null)
               splashDmgList.add(Game.checkForEnemy(target.getMidX()+delta1, target.getMidY()+delta1));

        }
        
        return splashDmgList;
    }
    
    public static final StateManager getInstance() 
    {
        return SingletonHolder.instance;
    }
    
    @SuppressWarnings("synthetic-access")
    public static class SingletonHolder
    {
        protected static final StateManager instance = new StateManager();
    }
}
